/* TotalDcmListerPluginView.h -- Source file for class TotalDcmListerPluginView
*
* TotalDcmLister - A lister plugin for Total Commander for listing DICOM File content.
*
* Copyright (C) 2015 Captain Stark
*
* This software may be modified and distributed under the terms of the MIT license.
* See the COPYRIGHT file at the top-level directory of this distribution for details.
*/

#include "stdafx.h"
#include "TotalDcmListerPluginView.h"
#include "TotalDcmListerAboutView.h"
#include "afxdialogex.h"

using namespace std;

IMPLEMENT_DYNAMIC(TotalDcmListerPluginView, CDialogEx)

/// <summary>
/// Initializes a new instance of the <see cref="TotalDcmListerPluginView"/> class.
/// </summary>
/// <param name="pParent">The parent window.</param>
TotalDcmListerPluginView::TotalDcmListerPluginView(CWnd* pParent /*=NULL*/)
   : CDialogEx(TotalDcmListerPluginView::IDD, pParent)
{
}

/// <summary>
/// Finalizes an instance of the <see cref="TotalDcmListerPluginView"/> class.
/// </summary>
TotalDcmListerPluginView::~TotalDcmListerPluginView()
{
}

/// <summary>
/// Does the dialog data exchange.
/// </summary>
/// <param name="pDX">A pointer to a CDataExchange object.</param>
void TotalDcmListerPluginView::DoDataExchange(CDataExchange* pDX)
{
   CDialogEx::DoDataExchange(pDX);
   DDX_Control(pDX, IDC_DICOMATTRIBUTELIST, m_ctrlDicomAttributeList);
   DDX_Control(pDX, IDC_HEADER, m_ctrlHeader);
   DDX_Control(pDX, IDC_ABOUTBUTTON, m_ctrlAboutButton);
}

BEGIN_MESSAGE_MAP(TotalDcmListerPluginView, CDialogEx)
   ON_WM_SIZE()
   ON_WM_CTLCOLOR()
   ON_BN_CLICKED(IDC_ABOUTBUTTON, &TotalDcmListerPluginView::OnBnClickedAboutbutton)
   ON_NOTIFY_EX(LVN_KEYDOWN, IDC_DICOMATTRIBUTELIST, &TotalDcmListerPluginView::OnKeydownInDicomAttributeList)
END_MESSAGE_MAP()

/// <summary>
/// Called in response to the WM_INITDIALOG message.
/// </summary>
/// <returns>True, when input focus is set to one of the controls in the dialog box. False otherwise.</returns>
BOOL TotalDcmListerPluginView::OnInitDialog()
{
   CDialogEx::OnInitDialog();

   SetupHeader();
   SetupListView();

   return TRUE;
}

/// <summary>
/// Called after the window's size has changed.
/// </summary>
/// <param name="nType">The type of resizing requested.</param>
/// <param name="width">The new width of the client area.</param>
/// <param name="height">The new height of the client area.</param>
void TotalDcmListerPluginView::OnSize(UINT nType, int width, int height)
{
   if (nullptr != m_ctrlAboutButton)
   {
      m_ctrlAboutButton.SetWindowPos(NULL, width - 65, 5, 60, 40, SWP_SHOWWINDOW);
   }

   if (nullptr != m_ctrlHeader)
   {
      m_ctrlHeader.SetWindowPos(NULL, 5, 2, width - 5, 48, SWP_SHOWWINDOW);
   }

   if (nullptr != m_ctrlDicomAttributeList)
   {
      m_ctrlDicomAttributeList.SetWindowPos(NULL, 0, 50, width, height, SWP_SHOWWINDOW);
   }
}

/// <summary>
/// Called by the framework when a child control is about to be drawn.
/// </summary>
/// <param name="pDC">Contains a pointer to the display context for the child window. May be temporary.</param>
/// <param name="pWnd">Contains a pointer to the control asking for the color. May be temporary.</param>
/// <param name="nCtlColor">Specifying the type of control.</param>
/// <returns>A handle to the brush that is to be used for painting the control background.</returns>
HBRUSH TotalDcmListerPluginView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
   if (nCtlColor == CTLCOLOR_STATIC && pWnd->m_hWnd == m_ctrlHeader.m_hWnd)
   {
      pDC->SetTextColor(RGB(0, 51, 153));
   }

   return (HBRUSH)GetStockObject(WHITE_BRUSH);
}


/// <summary>
/// Sets up the visual appearance of static header control. 
/// </summary>
void TotalDcmListerPluginView::SetupHeader()
{
   m_fontHeader.CreatePointFont(120, L"Segoe UI");

   m_ctrlHeader.SetFont(&m_fontHeader);
}

/// <summary>
/// Sets up the DICOM attribute list view.
/// Includes 2 columns, one for the DICOM Attribute name, one for the value.
/// </summary>
void TotalDcmListerPluginView::SetupListView()
{
   if (nullptr != m_ctrlDicomAttributeList)
   {
      m_ctrlDicomAttributeList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP );

      LVCOLUMN lvc;

      lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;

      lvc.iSubItem = 0;
      lvc.pszText = L"Attribute";
      lvc.cx = 200;
      lvc.fmt = LVCFMT_LEFT;

      m_ctrlDicomAttributeList.InsertColumn(0, &lvc);

      lvc.iSubItem = 1;
      lvc.pszText = L"Value";
      lvc.cx = 500;
      lvc.fmt = LVCFMT_LEFT;

      m_ctrlDicomAttributeList.InsertColumn(1, &lvc);
   }
}

/// <summary>
/// Sets the header text.
/// </summary>
/// <param name="text">The text.</param>
void TotalDcmListerPluginView::SetHeaderText(const wstring& text)
{
   m_ctrlHeader.SetWindowText(text.c_str());
}

/// <summary>
/// Adds a group to the DICOM attribute list.
/// </summary>
/// <param name="groupId">The group identifier.</param>
/// <param name="groupHeader">The group header.</param>
void TotalDcmListerPluginView::AddListViewGroup(const int groupId, const wstring& groupHeader)
{
   if (nullptr != m_ctrlDicomAttributeList)
   {
      m_ctrlDicomAttributeList.EnableGroupView(true);
      
      LVGROUP lvgrp = { sizeof(lvgrp) };

      lvgrp.mask = LVGF_HEADER | LVGF_GROUPID | LVGF_ALIGN;
      lvgrp.pszHeader = const_cast<LPWSTR>(groupHeader.c_str());
      lvgrp.cchHeader = wcslen(lvgrp.pszHeader);
      lvgrp.iGroupId = groupId;
      lvgrp.uAlign = LVGA_HEADER_LEFT;

      m_ctrlDicomAttributeList.InsertGroup(-1, &lvgrp);
   }
}

/// <summary>
/// Adds an item to the DICOM attribute list.
/// </summary>
/// <param name="groupId">The group identifier.</param>
/// <param name="attributeText">The attribute text.</param>
/// <param name="valueText">The value text.</param>
void TotalDcmListerPluginView::AddListViewItem(const int groupId, const wstring& attributeText, const wstring& valueText)
{
   if (nullptr != m_ctrlDicomAttributeList)
   {
      int itemIndex = m_ctrlDicomAttributeList.GetItemCount();

      LVITEM lvi;

      lvi.mask = LVIF_TEXT | LVIF_GROUPID;

      lvi.pszText = const_cast<LPWSTR>(attributeText.c_str());
      lvi.iItem = itemIndex;
      lvi.iSubItem = 0;
      lvi.iGroupId = groupId;

      m_ctrlDicomAttributeList.InsertItem(&lvi);

      m_ctrlDicomAttributeList.SetItemText(itemIndex, 1, (LPCTSTR)(valueText.c_str()));
   }
}

/// <summary>
/// Called when 'About' button was clicked. Opens a simple about dialog.
/// </summary>
void TotalDcmListerPluginView::OnBnClickedAboutbutton()
{
   TotalDcmListerAboutView aboutView(this);

   aboutView.DoModal();
}

/// <summary>
/// Called when the DICOM attribute list control received a WM_KEYDOWN message.
/// If ESCAPE key was pressed it's essential to let the plugin parent know this.
/// </summary>
/// <param name="id">The identifier of the sender.</param>
/// <param name="pNotifyStruct">Pointer to an NMLVKEYDOWN structure.</param>
/// <param name="pResult">The result.</param>
/// <returns>
/// TRUE when message has been handled, FALSE otherwise.
/// </returns>
BOOL TotalDcmListerPluginView::OnKeydownInDicomAttributeList(UINT id, NMHDR * pNotifyStruct, LRESULT *pResult)
{
   LPNMLVKEYDOWN pKeyDownMessage = reinterpret_cast<LPNMLVKEYDOWN>(pNotifyStruct);

   if (VK_ESCAPE == pKeyDownMessage->wVKey)
   {
      m_pParentWnd->SendMessage(WM_KEYDOWN, pKeyDownMessage->wVKey);
      *pResult = 0;

      return TRUE;
   }

   *pResult = 0;
   return FALSE;
}